/*
 * Copyright 2012 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.fieldscope.api;

import java.util.ArrayList;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

/**
 * Represents a station.
 * 
 * @author Travis Keep
 */
public class Station {
  
  private static final String LOCATION = "location";
  private static final String NAME = "name";
  private static final String ID = "id";
  private static final String SCHEMA = "schema";
  private final long id;
  private final String name;
  private final Location location;
  private final String schema;

  /**
   * The ID of this station as known by fieldscope server.
   */
  public long getId() {
    return id;
  }
  
  /**
   * Name of this station.
   */
  public String getName() {
    return name;
  }
  
  /**
   * Name of schema this station is associated with.
   */
  public String getSchema() {
    return schema;
  }
  
  /**
   * Location of this station.
   */
  public Location getLocation() {
    return location;
  }
  
  @Override
  public String toString() {
    return String.format("{id=%d, name=%s, location=%s, schema=%s}", id, name, location, schema);
  }
  
  /**
   * Serializes this object to a string.
   */
  public String marshall() {
    try {
      JSONObject json = new JSONObject();
      json.put(ID, id);
      if (name != null) {
        json.put(NAME, name);
      }
      if (location != null) {
        json.put(LOCATION, location.marshall());
      }
      if (schema != null) {
        json.put(SCHEMA, schema);
      }
      return json.toString();
    } catch (JSONException e) {
      throw new RuntimeException(e);
    }
  }

  /**
   * Reconstruct original object from value returned by {@link #marshall}
   */
  public static Station unmarshall(String s) {
    try {
      return newBuilder().unmarshall(new JSONObject(s)).build();
    } catch (JSONException e) {
      return null;
    }
  }
  
  /**
   * Return a new, empty builder.
   */
  public static Builder newBuilder() {
    return new Builder();
  }

  /**
   * Return new builder from a specific station.
   */
  public static Builder newBuilder(Station station) {
    return new Builder().setStation(station);
  }
  
  public static class Builder {
    private long id;
    private String name;
    private Location location;
    private String schema;
    
    public Builder setStation(Station station) {
      id = station.id;
      name = station.name;
      location = station.location;
      schema = station.schema;
      return this;
    }
    
    public Builder setId(long id) {
      this.id = id;
      return this;
    }
    
    public Builder setName(String name) {
      this.name = name;
      return this;
    }
    
    public Builder setLocation(Location location) {
      this.location = location;
      return this;
    }
    
    public Builder setSchema(String schema) {
      this.schema = schema;
      return this;
    }
    
    public Station build() {
      return new Station(this);
    }
    
    Builder unmarshall(JSONObject json) throws JSONException {
      id = json.getLong(ID);
      name = json.has(NAME) ? json.getString(NAME) : null;
      schema = json.has(SCHEMA) ? json.getString(SCHEMA) : null;
      location = json.has(LOCATION) ? Location.unmarshall(json.getString(LOCATION)) : null;
      return this;
    }
    
    private Builder() {
    }
  }
  
  static List<Station> fromJSON(Builder builder, JSONObject json) throws JSONException {
    JSONArray results = json.getJSONArray("results");
    List<Station> result = new ArrayList<Station>(results.length());
    for (int i = 0; i < results.length(); i++) {
      result.add(singleFromJSON(builder, results.getJSONObject(i)));
    }
    return result;
  }
  
  private Station(Builder builder) {
    this.id = builder.id;
    this.name = builder.name;
    this.location = builder.location;
    this.schema = builder.schema;
  }
  
  private static Station singleFromJSON(Builder builder, JSONObject jsonObject) throws JSONException {
    builder.setId(jsonObject.getLong(ID));
    builder.setName(jsonObject.getString(NAME));
    builder.setLocation(Location.parseFromJSON(jsonObject.getString(LOCATION)));
    return builder.build();
  }
}
